import com.formdev.flatlaf.FlatDarkLaf;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.JTextComponent;
import java.awt.*;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 比较两JSON对象是否相同的小程序
 */
public class CheckJsonFrame extends JFrame {
	private static final int WIDTH = 1200;
	private static final int HEIGHT = 700;
	private boolean isUpdate = false;
	private JLabel leftLabel;
	private JLabel rightLabel;
	private JLabel resultLabel; //比较结果
	private JTextArea tipTextArea; //不相等原因
	private JTextArea leftTextArea;
	private JTextArea rightTextArea;

	private ArrayList<JCheckBox> checkBoxes;
	private JButton compareButton;
	private JButton resetButton;

	private JsonSameUtil jsonSameUtil;

	public CheckJsonFrame() {
		initService();
		initComponent();
		initListener();
		initLayout();
	}

	public static void main(String[] args) {
		FlatDarkLaf.setup();
		EventQueue.invokeLater(() -> new CheckJsonFrame().setVisible(true));
	}

	private static String processIndent(String text) {
		String reg = "\t";
		Pattern patten = Pattern.compile(reg);
		Matcher matcher = patten.matcher(text);
		StringBuilder builder = new StringBuilder();
		while (matcher.find()) {
			builder.append(matcher.replaceAll("  "));
		}
		// 第二次匹配会变成空串
		return builder.toString().equals("") ? text : builder.toString();
	}

	private void initService() {
		jsonSameUtil = new JsonSameUtil();
	}

	private void initComponent() {
		Font titleFont = new Font("Microsoft YaHei UI", Font.BOLD, 20);
		Font contentFont = new Font("Microsoft YaHei UI", Font.PLAIN, 12);
		leftLabel = new JLabel("a(新版)");
		leftLabel.setFont(titleFont);
		rightLabel = new JLabel("b(原版)");
		rightLabel.setFont(titleFont);
		resultLabel = new JLabel("", SwingConstants.CENTER);
		resultLabel.setFont(titleFont);
		resultLabel.setPreferredSize(new Dimension(WIDTH, 30));
		tipTextArea = new JTextArea();
		leftTextArea = new JTextArea();
		leftTextArea.setFont(contentFont);
		leftTextArea.setTabSize(1);
		rightTextArea = new JTextArea();
		rightTextArea.setFont(contentFont);
		rightTextArea.setTabSize(1);

		checkBoxes = new ArrayList<>();
		checkBoxes.add(new JCheckBox("a包含b"));
		checkBoxes.add(new JCheckBox("忽略字符串中空格"));
		checkBoxes.add(new JCheckBox("忽略数组顺序"));

		compareButton = new JButton("比较");
		compareButton.setPreferredSize(new Dimension(80, 30));
		resetButton = new JButton("清空");
		resetButton.setPreferredSize(new Dimension(80, 30));
	}

	private void initListener() {
		compareButton.addActionListener(e -> {
			boolean isContain = checkBoxes.get(0).isSelected();
			boolean ignoreStrSpace = checkBoxes.get(1).isSelected();
			boolean arrayIgnoreOrder = checkBoxes.get(2).isSelected();
			jsonSameUtil.setaContainB(isContain)
					.setIgnoreStrSpace(ignoreStrSpace)
					.setArrayIgnoreOrder(arrayIgnoreOrder);

			String leftText = leftTextArea.getText();
			String rightText = rightTextArea.getText();
			String same = jsonSameUtil.same(leftText, rightText);
			if (same == null) {
				tipTextArea.setText("");
				resultLabel.setText("true");
				resultLabel.setForeground(new Color(39, 174, 96));
			} else {
				tipTextArea.setText(same);
				resultLabel.setText("false");
				resultLabel.setForeground(new Color(231, 76, 60));
			}
		});

		resetButton.addActionListener(e -> {
			leftTextArea.setText("");
			rightTextArea.setText("");
		});

		// 失去焦点时格式化一下，为了更直观
		leftTextArea.addFocusListener(new FocusAdapter() {
			@Override
			public void focusLost(FocusEvent e) {
				if (isUpdate) {
					leftTextArea.setText(processIndent(leftTextArea.getText()));
					isUpdate = false;
				}
			}
		});
		rightTextArea.addFocusListener(new FocusAdapter() {
			@Override
			public void focusLost(FocusEvent e) {
				if (isUpdate) {
					rightTextArea.setText(processIndent(rightTextArea.getText()));
					isUpdate = false;
				}
			}
		});

		addUpdateListener(leftTextArea);
		addUpdateListener(rightTextArea);
	}

	private void addUpdateListener(JTextComponent component) {
		component.getDocument().addDocumentListener(new DocumentListener() {
			@Override
			public void insertUpdate(DocumentEvent e) {
				isUpdate = true;
			}

			@Override
			public void removeUpdate(DocumentEvent e) {
				isUpdate = true;
			}

			@Override
			public void changedUpdate(DocumentEvent e) {
				isUpdate = true;
			}
		});
	}

	private void initLayout() {
		JPanel topPanel = new JPanel(new BorderLayout());
		topPanel.add(leftLabel, BorderLayout.WEST);
		topPanel.add(rightLabel, BorderLayout.EAST);

		JPanel centerPanel = new JPanel(new BorderLayout());
		JPanel jsonTextPanel = new JPanel(new GridLayout(1, 2));
		jsonTextPanel.add(new JScrollPane(leftTextArea));
		jsonTextPanel.add(new JScrollPane(rightTextArea));

		JPanel checkBoxPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
		checkBoxes.forEach(checkBoxPanel::add);
		JPanel buttonPanel = new JPanel();
		buttonPanel.add(compareButton);
		buttonPanel.add(resetButton);
		JPanel opePanel = new JPanel(new BorderLayout());
		opePanel.add(checkBoxPanel, BorderLayout.NORTH);
		opePanel.add(buttonPanel, BorderLayout.SOUTH);
		centerPanel.add(jsonTextPanel);
		centerPanel.add(opePanel, BorderLayout.SOUTH);

		JScrollPane tipScrollPane = new JScrollPane(tipTextArea);
		tipScrollPane.setPreferredSize(new Dimension(WIDTH, 130));
		JPanel bottomPanel = new JPanel(new BorderLayout());
		bottomPanel.add(resultLabel, BorderLayout.NORTH);
		bottomPanel.add(tipScrollPane);

		Container contentPane = getContentPane();
		contentPane.add(topPanel, BorderLayout.NORTH);
		contentPane.add(centerPanel);
		contentPane.add(bottomPanel, BorderLayout.SOUTH);

		setTitle("JSON数据比较器");
		setSize(new Dimension(WIDTH + 25, HEIGHT + 20));
		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		setLocationRelativeTo(null);
	}
}
